package com.atguigu.gmall.activity.receiver;

import com.atguigu.gmall.activity.mapper.SeckillGoodsMapper;
import com.atguigu.gmall.activity.service.SeckillGoodsService;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.DateUtil;
import com.atguigu.gmall.model.activity.SeckillGoods;
import com.atguigu.gmall.model.activity.UserRecode;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rabbitmq.client.Channel;
import lombok.SneakyThrows;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;


//秒杀商品的监听器
@Component
public class SeckillReceiver {
    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SeckillGoodsService seckillGoodsService;

    //定时将当天的秒杀商品存到redis中去，监听消息队列
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_TASK_1,durable = "true",autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_TASK),
            key = {MqConst.ROUTING_TASK_1}
    ))
    public void importToRedis(Message message, Channel channel){
        //从数据库查询当天的秒杀商品，并保存到Redis中
        //条件：秒杀开始时间（天）于当天日期对应，状态位status字段为1，库存数量大于0
        QueryWrapper<SeckillGoods> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("DATE_FORMAT(start_time,'%Y-%m-%d')", DateUtil.formatDate(new Date()));
        queryWrapper.eq("status", "1");
        queryWrapper.gt("stock_count",0);
        List<SeckillGoods> seckillGoodsList = seckillGoodsMapper.selectList(queryWrapper);

        //准备放入redis,类型为Hash , key 为 RedisConst.SECKILL_GOODS
        if (!CollectionUtils.isEmpty(seckillGoodsList)){
            for (SeckillGoods seckillGoods : seckillGoodsList) {
                String seckillKey = RedisConst.SECKILL_GOODS;
                Boolean flag = redisTemplate.boundHashOps(seckillKey).hasKey(seckillGoods.getSkuId().toString());
                if (flag){
                    continue;
                }
                //将该秒杀商品信息存入redis，RedisConst.SECKILL_GOODS为总Hash的key，feild为该商品
                // seckillGoods的skuId（toString）
                redisTemplate.boundHashOps(seckillKey).put(seckillGoods.getSkuId().toString(),seckillGoods);

                //为防止商品超卖，把库存数单独再存到redis中list类型，RedisConst.SECKILL_STOCK_PREFIX + seckillGoods.getSkuId()为Key
                //有多少库存，就向该list中存入多少个值，值为该商品的skuId（toString）
                for (int i = 0; i < seckillGoods.getStockCount(); i++) {
                    String stockKey = RedisConst.SECKILL_STOCK_PREFIX + seckillGoods.getSkuId();
                    redisTemplate.opsForList().leftPush(stockKey,seckillGoods.getSkuId().toString());
                }
                //初始化状态位，redis中发布频道消息,
                redisTemplate.convertAndSend("seckillpush",seckillGoods.getSkuId()+":1");

            }
        }

        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }

    //监听消息队列,进行秒杀下单，传过来的UserRecode 封装了userId 和 秒杀商品的skuId
    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_SECKILL_USER,durable = "true",autoDelete = "false"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_SECKILL_USER),
            key = {MqConst.ROUTING_SECKILL_USER}
    ))
    public void seckillOrder(UserRecode userRecode, Message message, Channel channel){
        if (userRecode != null){
            seckillGoodsService.seckillOrder(userRecode.getSkuId(),userRecode.getUserId());
        }
    }

}
